
package com.lee.tree; 
 
import com.lee.logger.Logger; 
import lombok.Data; 
import org.apache.commons.lang3.ObjectUtils; 
import org.apache.commons.lang3.StringUtils; 
 
import java.util.*; 
 
@Data 
public class FPNode { 
    transient private FPTree tree;
    private String item;
    private Long count;
    transient private FPNode parent;
    transient private Map<String,FPNode> children;
    transient private FPNode neighbor;
    public FPNode(FPTree tree,String item,Long count){
        this.setTree(tree);
        this.setItem(item);
        this.setCount(count);
        //this.setParent(null);
        Map<String,FPNode> children = new HashMap<>();
        this.setChildren(children);
        //this.setNeighbor(null);
    }
    public FPNode(FPTree tree,String item){
        this(tree,item,1l);
    }
    public void add(FPNode child){
 
        if(!this.getChildren().containsKey(child.getItem())){
            this.getChildren().put(child.getItem(),child);
            child.setParent(this);
        }
    }
    public FPNode search(String item){
        if(this.getChildren().containsKey(item)){
            return this.getChildren().get(item);
        }
        return null;
    }
    public boolean contains(String item){
        return this.getChildren().containsKey(item) ;
    }
 
    public void increment(){
        this.setCount(this.getCount() + 1);
    }
 
 
    public boolean isRoot(){
        return StringUtils.isBlank(this.getItem()) && this.getCount() == null;
    }
 
    public boolean isLeaf(){
        return this.getChildren().size() == 0;
    }
 
    public Set<FPNode> allChildren(){
        return new HashSet<>(this.getChildren().values());
    }
 
    public void inspect(){
        this.inspect(0);
    }
    public void inspect(int depth){
        FPNode tmp = this;
        List<String> path = new ArrayList();
        List<Long> count = new ArrayList();
        while(!tmp.isRoot()){
            path.add(tmp.getItem());
            count.add(tmp.getCount());
            tmp = tmp.getParent();
        }
        Collections.reverse(path);
        Collections.reverse(count);
        if(path.contains("B1") && path.contains("C2") && path.contains("D2") && path.get(path.size() - 1).equals("D2")){
            Logger.info("inspect ",path,count);
        }
//        Logger.info(String.join("", Collections.nCopies(depth," ")) + repr());
 
        for(FPNode child:this.allChildren()){
            child.inspect(depth + 1);
        }
    }
 
    public String repr(){
        if (this.isRoot()){
            return String.format("<%s (root)>",this.getClass().getName());
        } else {
            return String.format("<%s %s (%d)>",this.getClass().getName(),this.getItem(),this.getCount());
        }
    }
 
 
    @Override
    public String toString() {
 
        return String.format("FPNode{%s}(%d)",this.item,this.count);
    }
 
    public FPTree getTree() {
        return tree;
    }
 
    public void setTree(FPTree tree) {
        this.tree = tree;
    }
 
    public String getItem() {
        return item;
    }
 
    public void setItem(String item) {
        this.item = item;
    }
 
    public Long getCount() {
        return count;
    }
 
    public void setCount(Long count) {
        this.count = count;
    }
 
    public FPNode getParent() {
        return parent;
    }
 
    public void setParent(FPNode parent) {
        this.parent = parent;
    }
 
    public Map<String, FPNode> getChildren() {
        return children;
    }
 
    public void setChildren(Map<String, FPNode> children) {
        this.children = children;
    }
 
    public FPNode getNeighbor() {
        return neighbor;
    }
 
    public void setNeighbor(FPNode neighbor) {
        this.neighbor = neighbor;
    }
} 
